package com.tian.framework.security.config;

import com.tian.framework.security.handler.*;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;


@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)//只能启用一次 在SecurityConfig已启用
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
    @Autowired
    private OwnAuthenticationProvider securityAuthenticationProvider;
    @Autowired
    EntryPointImpl entryPoint;

    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        //KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        //.setGrantedAuthoritiesMapper(grantedAuthority());
        auth.authenticationProvider(securityAuthenticationProvider);
    }

    //忽略静态资源
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/static/**", "/favicon.ico");
    }

    //当不想要有会话，创建无状态REST服务时
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new NullAuthenticatedSessionStrategy();
    }

    /**
     * Secure appropriate endpoints
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        // 开启允许iframe 嵌套
        http.headers().frameOptions().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
        // 过滤
        http.addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
                .addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
                .addFilterBefore(keycloakAuthenticatedActionsRequestFilter(), BasicAuthenticationFilter.class)
                .addFilterAfter(keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class);
        //启用跨域
        http.csrf().disable().cors();
        //认证,必须设置authenticated,然后再配置登录效验authenticationEntryPoint继承KeycloakAuthenticationEntryPoint类
        //设置允许任何人可以访问login中方法
        //http.authorizeRequests().antMatchers("/login/**").permitAll();
        //security与Keycloak权限对接是通过entryPoint
        //http.authorizeRequests().anyRequest().authenticated();
        http.authorizeRequests().anyRequest().permitAll();
        //security与Keycloak权限处理
        //http.exceptionHandling().authenticationEntryPoint(entryPoint);
    }

    @Bean
    @Override
    @ConditionalOnMissingBean(HttpSessionManager.class)
    protected HttpSessionManager httpSessionManager() {
        return new HttpSessionManager();
    }
}
